﻿
Imports System.Runtime.CompilerServices
Imports osi.root.constants
Imports osi.root.connector
Imports osi.root.utils

Public Module _piece
    <Extension()> Public Function null_or_empty(ByVal this As piece) As Boolean
        Return this Is Nothing OrElse this.empty()
    End Function
End Module

Public Class piece
    Public ReadOnly buff() As Byte
    Public ReadOnly offset As UInt32
    Public ReadOnly count As UInt32

    Shared Sub New()
        binder(Of Func(Of piece, UInt64), sizeof_binder_protector).set_global(Function(i As piece) As UInt64
                                                                                  Return If(i Is Nothing, 0, i.count)
                                                                              End Function)
    End Sub

    Public Shared Function valid(ByVal buff() As Byte,
                                 ByVal offset As UInt32,
                                 ByVal count As UInt32) As Boolean
        Return array_size(buff) >= offset + count
    End Function

    Private Sub assert_valid()
        assert(valid(buff, offset, count))
    End Sub

    Public Sub New(ByVal buff() As Byte,
                   ByVal offset As UInt32,
                   ByVal count As UInt32)
        Me.buff = buff
        Me.offset = offset
        Me.count = count
        assert_valid()
    End Sub

    Public Sub New(ByVal buff() As Byte,
                   ByVal count As UInt32)
        Me.New(buff, uint32_0, count)
    End Sub

    Public Sub New(ByVal buff() As Byte)
        Me.New(buff, array_size(buff))
    End Sub

    Public Function empty() As Boolean
        Return count = uint32_0
    End Function

    Public Function consume(ByVal size As UInt32, ByRef o As piece) As Boolean
        If size > count Then
            Return False
        Else
            o = New piece(buff, offset + size, count - size)
            Return True
        End If
    End Function

    Public Function consume(ByVal size As UInt32) As piece
        Dim r As piece = Nothing
        assert(consume(size, r))
        Return r
    End Function

    Public Function consume_back(ByVal size As UInt32, ByRef o As piece) As Boolean
        If size > count Then
            Return False
        Else
            o = New piece(buff, offset, count - size)
            Return True
        End If
    End Function

    Public Function consume_back(ByVal size As UInt32) As piece
        Dim r As piece = Nothing
        assert(consume_back(size, r))
        Return r
    End Function

    Public Shared Function create(ByVal buff() As Byte,
                                  ByVal offset As UInt32,
                                  ByVal count As UInt32,
                                  ByRef o As piece) As Boolean
        If valid(buff, offset, count) Then
            o = New piece(buff, offset, count)
            Return True
        Else
            Return False
        End If
    End Function

    Public Shared Function create(ByVal buff() As Byte,
                                  ByVal count As UInt32,
                                  ByRef o As piece) As Boolean
        Return create(buff, uint32_0, count, o)
    End Function

    Public Shared Function create(ByVal buff() As Byte,
                                  ByRef o As piece) As Boolean
        Return create(buff, array_size(buff), o)
    End Function

    Public Shared Function create(ByRef o As piece) As Boolean
        Return create(Nothing, o)
    End Function
End Class
